/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.seguradora.model.repository.impl;

import br.com.seguradora.exception.PersistenciaException;
import br.com.seguradora.model.Grupo;
import br.com.seguradora.model.repository.TodosGrupos;
import br.com.seguradora.persistence.GerenciadorDeConexao;
import br.com.seguradora.view.DisplayFilter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Diego
 */
public class TodosGruposImpl implements TodosGrupos {

    private Connection conn;
    private PreparedStatement pr;
    private ResultSet rs;

    @Override
    public boolean inserir(Grupo grupo) throws PersistenciaException {
        if (grupo == null) {
            throw new PersistenciaException("Não foi informado o grupo a cadastrar.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("INSERT INTO GRUPO(ID, BLOQUEADO, NOME, SHADOW) VALUES(NULL, FALSE, ?, FALSE);",
                    Statement.RETURN_GENERATED_KEYS);
            pr.setString(1, grupo.getNome());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
                rs = pr.getGeneratedKeys();
                rs.first();
                long id = rs.getLong(1);
                grupo.setId(id);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível cadastrar o grupo.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return sucesso;
    }

    @Override
    public boolean atualizar(Grupo grupo) throws PersistenciaException {
        if (grupo == null) {
            throw new PersistenciaException("Não foi informado o grupo a atualizar.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("UPDATE GRUPO SET BLOQUEADO=?, NOME=? WHERE ID=?;");
            pr.setBoolean(1, grupo.isBloqueado());
            pr.setString(2, grupo.getNome());
            pr.setLong(3, grupo.getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível atualizar o grupo.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
        return sucesso;
    }

    @Override
    public boolean excluir(Grupo grupo) throws PersistenciaException {
        if (grupo == null) {
            throw new PersistenciaException("Não foi informado o grupo a excluir.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("UPDATE GRUPO SET SHADOW=TRUE WHERE ID=?;");
            pr.setLong(1, grupo.getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível excluir o grupo.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
        return sucesso;
    }

    @Override
    public List<Grupo> listarTodos() throws PersistenciaException {
        List<Grupo> lista = new ArrayList<Grupo>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT ID, BLOQUEADO, NOME FROM GRUPO WHERE SHADOW=FALSE ORDER BY ID DESC");
            rs = pr.executeQuery();
            while (rs.next()) {
                Grupo grupo = this.criarGrupo(rs);
                lista.add(grupo);
            }
            if (!lista.isEmpty()) {
                contabilizarCotas(lista);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os grupos.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    private Grupo criarGrupo(ResultSet rs) throws PersistenciaException {
        Grupo grupo = null;
        try {
            grupo = new Grupo(rs.getLong("ID"), rs.getBoolean("BLOQUEADO"), rs.getString("NOME"));
        } catch (SQLException sqlex) {
            StringBuilder msg = new StringBuilder("Não foi possível obter os dados do grupo.");
            msg.append("\nMotivo: ").append(sqlex.getMessage());
            throw new PersistenciaException(msg.toString());
        }
        return grupo;
    }

    @Override
    public List<Grupo> listarPeloNome(String nome, DisplayFilter displayFilter) throws PersistenciaException {
        List<Grupo> lista = new ArrayList<Grupo>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            if (displayFilter != DisplayFilter.TODOS) {
                pr = conn.prepareStatement("SELECT ID, BLOQUEADO, NOME FROM GRUPO WHERE SHADOW=FALSE AND NOME LIKE ? AND BLOQUEADO=? ORDER BY NOME");
                pr.setBoolean(2, displayFilter.getValue());
            } else {
                pr = conn.prepareStatement("SELECT ID, BLOQUEADO, NOME FROM GRUPO WHERE SHADOW=FALSE AND NOME LIKE ? ORDER BY NOME");
            }
            pr.setString(1, "%" + nome + "%");
            rs = pr.executeQuery();
            while (rs.next()) {
                Grupo grupo = this.criarGrupo(rs);
                lista.add(grupo);
            }
            if (!lista.isEmpty()) {
                contabilizarCotas(lista);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os grupos.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    @Override
    public List<Grupo> listarDesbloqueados() throws PersistenciaException {
        List<Grupo> lista = new ArrayList<Grupo>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT ID, BLOQUEADO, NOME FROM GRUPO WHERE BLOQUEADO=FALSE AND SHADOW=FALSE ORDER BY NOME");
            rs = pr.executeQuery();
            while (rs.next()) {
                Grupo grupo = this.criarGrupo(rs);
                lista.add(grupo);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os grupos desbloqueados.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    private void contabilizarCotas(List<Grupo> grupoList) throws PersistenciaException {
        PreparedStatement pr = null;
        ResultSet rs = null;
        try {
            pr = conn.prepareStatement("SELECT G.NOME AS GRUPO, SUM(V.COTAS) AS COTAS FROM VEICULO V INNER JOIN GRUPO G ON V.ID_GRUPO = G.ID WHERE G.ID=?");
            for (Grupo grupo : grupoList) {
                pr.setLong(1, grupo.getId());
                rs = pr.executeQuery();
                if (rs.first()) {
                    grupo.setTotalCotas(rs.getDouble("COTAS"));
                }
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível contabilizar as cotas por grupos.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(null, pr, rs);
        }
    }
}
